使用Github Actions自动打包Go项目


前言

如果用过 Gitlab Ci, 相信对此也非常熟悉,GitHub ActionsGitHub 推出的持续集成(Continuous Integration,简称 CI)服务,它提供了整套虚拟服务器环境,基于它可以进行构建、测试、打包、部署项目等等操作

快速开始(Quickstart)

在自己的 Github 仓库中找到 Actions 标签页

点击 Configure, 此时会生成一个 .github/workflow/go.yml 文件

# This workflow will build a golang project
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-go

name: Go

on:
  push:
    branches: [ "master" ]
  pull_request:
    branches: [ "master" ]

jobs:

  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
        - name: Set up Go
          uses: actions/setup-go@v3
        with:
          go-version: 1.19
      - name: Build
        run: go build -v ./...
      - name: Test
        run: go test -v ./...

多平台编译(Cross Compile)

交叉编译

对于非 CGO 项目,Go 提供了一种十分方便的方式来进行交叉编译,只需要指定 GOOSGOARCH 环境变量

  • Mac下编译Linux, Windows平台的64位可执行程序:

    $ CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build .
    $ CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build .
  • Linux下编译Mac, Windows平台的64位可执行程序:

    $ CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build .
    $ CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build .

同样的,我们可以在 Gtihub Actions 中设置环境变量来编译非 CGO 项目,这里需要使用 matrix 策略,让我们基于不同的参数创建并行的任务,比如编译Go时指定不同的环境变量

  • 首先编写任务

    jobs:
      build:
        strategy:
          matrix:
            goos: [linux, darwin]
            goarch: [amd64]
    
        runs-on: ubuntu-latest
    
        steps:
          - name: Checkout
            uses: actions/checkout@v3
          - name: Set up Go
            uses: actions/setup-go@v3
            with:
              go-version: 1.19
          - name: Download dependencies
            run: go mod download
          - name: Build
            run: go build -v -o snow .
            # 指定编译时的环境变量
            env:
              GOOS: ${{ matrix.goos }}
              GOARCH: ${{ matrix.goarch }}
              CGO_ENABLED: 0

    这样就创建了 GOOS=linux GOARCH=amd64GOOS=darwin GOARCH=amd64 的两个任务, 当 goarch 增加一个 arm 的参数后,会组合成四个任务, 如果需要指定或者排除某个选项,可以使用 include 或者 exclude

    matrix:
      goos: [linux, darwin]
      goarch: [amd64, arm]
      # 只包括linux编译选项
      include:
        - goos: linux
          goarch: amd64
        - goos: linux
          goarch: arm
      # 排除所有关于arm的编译选项
      exclude:
        - goarch: arm
  • 然后执行 git push, 这样就能在 GithubActions 标签页看到执行结果

跨平台编译

如果是非 CGO 项目,可以使用Go内置的交叉编译,但如果是 CGO 项目,上述的交叉编译大概率会失败(相关问题:go-libsass), 所以我们需要基于不同的平台来进行编译,幸运的是,Github Actions 对此支持的非常好,

  • 编写新任务

    jobs:
      build:
        strategy:
          matrix:
            build: [macos, linux]
            include:
              - build: macos
                os: macos-latest
              - build: linux
                os: ubuntu-18.04
        runs-on: ${{ matrix.os }}
        steps:
          - name: Checkout
            uses: actions/checkout@v3
          - name: Set up Go
            uses: actions/setup-go@v3
            with:
              go-version: 1.19
          - name: Download dependencies
            run: go mod download
          - name: Build
            run: go build -v -o snow .
            env:
              CGO_ENABLED: 1

    注意 runs-on 使用的 matrix.os 变量, 它允许我们分别使用 ubuntu-18.04macos-latest 两个平台进行编译,这时不用指定 GOOSGOARCH 参数

  • 执行 git push, 可以看到执行结果

发布(Release)

当编译好一个二进制文件后,需要发布到 GithubRelease 页,这时就需要添加新的任务, 目前官方的actions/create-release已经无人维护,所以此次选择另外一个ncipollo/release-action

name: Release

on:
  # 只在预发布时才执行
  release:
    types: [prereleased]

jobs:
  build:
    strategy:
      matrix:
        build: [macos, linux]
        include:
          - build: macos
            os: macos-latest
            archive-name: darwin.tar.gz
          - build: linux
            os: ubuntu-latest
            archive-name: linux.tar.gz

    # 需要设置写权限才能自动发布
    permissions:
      contents: write

    steps:
      ...
      # 把二进制文件打包成压缩文件
      - name: Prepare Packaging
        run: tar zcvf snow-${{ matrix.archive-name }}.tar.gz snow LICENSE

      # 上传附件
      - name: Upload Artifacts
        uses: actions/upload-artifact@v3
        with:
          name: snow-${{ matrix.archive-name }}.tar.gz
          path: snow-${{ matrix.archive-name }}.tar.gz

      # 发布release版本
      - name: Release version
        uses: ncipollo/release-action@v1
        if: github.event_name == 'release'
        with:
          allowUpdates: true
          artifacts: snow-${{ matrix.archive-name }}.tar.gz
          token: ${{ secrets.GITHUB_TOKEN }}

Github Actions 执行完成后,就能在 Release 页看到我们发布的 Package

FAQ

version `GLIBC_2.33' not found

使用 Github Actions 发布一个新的版本,下载到本地执行时报错

./snow: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.33' not found (required by ./snow)
./snow: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.34' not found (required by ./snow)
./snow: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.32' not found (required by ./snow)
./snow: /usr/lib/x86_64-linux-gnu/libstdc++.so.6: version `GLIBCXX_3.4.29' not found (required by ./snow)

这是由于使用的 ubuntu 版本太高导致, 降低版本即可

include:
...
-   os: ubuntu-latest
+   os: ubuntu-18.04

Bad CPU type in executable

这是由于最新的 macos-latest 仅包括arm64,不再包括x86_64导致,如果需要使用x86_64,请指定版本 macos-13

作者: honmaple
链接: https://honmaple.me/articles/2023/03/使用Github Actions自动打包Go项目.html
版权: CC BY-NC-SA 4.0 知识共享署名-非商业性使用-相同方式共享4.0国际许可协议
wechat
alipay

加载评论